home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / genexp.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  14KB  |  514 lines

  1. /*
  2.  * @(#)genexp.c    1.7  2/23/90
  3.  */
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <errno.h>
  7.  
  8. #include "assert.h"
  9. #include "addresses.h"
  10. #include "nodes.h"
  11. #include "map.h"
  12. #include "sequence.h"
  13. #include "system.h"
  14. #include "semantics.h"
  15. #include "builtins.h"
  16. #include "evaluate.h"
  17. #include "opNames.h"
  18. #include "primitives.h"
  19. #include "allocate.h"
  20. #include "MyParser.h"
  21. #include "datadesc.h"
  22. #include "environment.h"
  23. #include "regdefs.h"
  24. #include "genutils.h"
  25. #include "emit.h"
  26. #include "error.h"
  27. #include "consts.h"
  28. #include "flags.h"
  29. #include "trace.h"
  30. #include "option.h"
  31.  
  32. /*
  33.  * Imported routines
  34.  */
  35. extern void moveDataToRegister(), moveVariableToRegisters(), claimReg();
  36. extern void resolveGlobal();
  37. extern void findTemp();
  38. extern DD generateCreation();
  39. extern Boolean isARealImport();
  40. extern NodePtr newExecuteAsAT(), tryToExecuteAsAT();
  41. extern void generateInvocation();
  42. extern NodePtr buildOpName();
  43. /*
  44.  * Global variables
  45.  */
  46.  
  47. extern int cEM_locates;
  48.  
  49. /*
  50.  * Exported definitions
  51.  */
  52.  
  53. /*
  54.  * Local definitions
  55.  */
  56.  
  57. /*
  58.  * Forward definitions
  59.  */
  60.  
  61. void generateExpression(), generateExp(), generateUnaryExp();
  62. void generate(), generateVectorLiteral();
  63.  
  64. void generateExpression(p, c)
  65. NodePtr p;
  66. Context c;
  67. {
  68.   Variable result, *v;
  69.   register Symbol st;
  70.   NodePtr setqs, q, r;
  71.   Symbol sym;
  72.  
  73.   assert((int)p >= 0x200);
  74.   result.data = nullDD;
  75.   result.abCon = nullDD;
  76.   switch (p->tag) {
  77.     case P_ARG:
  78.       /* ignore p->b.arg.move */
  79.       generateExpression(p->b.arg.exp, c);
  80.       break;
  81.     case P_SYMDEF:
  82.     case P_SYMREF:
  83.       st = ST_Fetch(p->b.symref.symbol);
  84.       vPushSymbol(st, c);
  85.       break;
  86.     case P_BUILTINLIT:
  87.     case P_NILLIT:
  88.     case P_BOOLLIT:
  89.     case P_INTLIT:
  90.     case P_STRINGLIT:
  91.     case P_CHARLIT:
  92.     case P_REALLIT:
  93.       vPushValue(p, c);
  94.       break;
  95.     case P_GLOBALREF:
  96.       resolveGlobal(p, (ValuePtr) NULL);
  97.       generateExpression(p->b.globalref.value, c);
  98.       break;
  99.     case P_ATLIT:
  100.       generate(p);
  101.       vPushValue(p, c);
  102.       break;
  103.     case P_OBLIT:
  104.       generate(p);
  105.       result.abCon = buildAbConFromObject(p);
  106.       if (p == currentObject) {
  107.     result.data.kind = DD_Self;
  108.       } else if (p->b.oblit.f.writeSeparately) {
  109.     /*
  110.      * This is an object that the compiler created, so the value of this
  111.      * expression is just a reference to the object.  
  112.      */
  113.     result.data.kind = DD_OIDToODP;
  114.     result.data.value.id = p->b.oblit.id;
  115.       } else if (p->b.oblit.f.isTypeVariable ||
  116.          p->b.oblit.f.dependsOnTypeVariable) {
  117.     ErrorMessage(p,
  118.       "This object depends on a type parameter and cannot be created");
  119.       } else {
  120.      /*
  121.      * This is needs to be translated into a call of the kernel.create
  122.      * primitive to actually build a new object.
  123.      */
  124.     /*
  125.      * Allocate the space on the stack for the result.
  126.      */
  127.     IFOPTION(createonstack, 1 &&
  128.       p->b.oblit.codeOID != OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
  129.       emitMove(result.abCon, pusher, 'l');
  130.       emitMove(nilDD, pusher, 'l');
  131.     }
  132.     /*
  133.      * Prepare the parameters to the initially of the object.
  134.      */
  135.     setqs = p->b.oblit.setq;
  136.     Sequence_For(q, setqs)
  137.       /*
  138.        * Charge through the setq list and find the non-manifest ones and
  139.        * push their values on the stack.
  140.        */
  141.       assert(q->tag == P_SETQ);
  142.       r = q->b.setq.inner;
  143.       assert(r->tag == P_SYMDEF);
  144.       sym = ST_Fetch(r->b.symdef.symbol);
  145.       if (isARealImport(sym, TRUE)) {
  146.         /*
  147.          * This is a real import.  We need to push the current value of 
  148.          * outer on the stack.
  149.          */
  150.         r = q->b.setq.outer;
  151.         vPush(pusherContext.v);
  152.         generateExpression(r, pusherContext);
  153.         vGenerateAssign();
  154.       }
  155.     Sequence_Next
  156.     result.data = generateCreation(p, FALSE, 
  157.       (Boolean)(OPTION(locals,1) && p->b.oblit.f.doLocalCreate));
  158.       }
  159.       vPush(result);
  160.       break;
  161.     case P_INVOC:
  162.       generateInvocation(p, 1, c);
  163.       break;
  164.     case P_EXP:
  165.       generateExp(p, c);
  166.       break;
  167.     case P_UNARYEXP:
  168.       generateUnaryExp(p, c);
  169.       break;
  170.     case P_VECTORLIT:
  171.       generateVectorLiteral(p);
  172.       break;
  173.     case P_VIEW:
  174.       generateExpression(p->b.view.exp, anyContext);
  175.       if (p->b.view.isRedundant) {
  176.     IFOPTION(comment, 1) Comment("\t\t\t\tRedundant view expression");
  177.       } else {
  178.     v = vPeek(0);
  179.     q = newExecuteAsAT(p->b.view.type);
  180.     assert(q->tag == P_ATLIT);
  181.     moveVariableToRegisters(v, regs_arg1);
  182.     IFOPTION(view, 1) {
  183.       result.data = buildManifestDD((int)q->b.atlit.id);
  184.       ensureGenerate(q->b.atlit.id);
  185.       result.abCon = buildConCon(INTEGERINDEX);
  186.       moveDataToRegister(&result, regs_arg3, DataBrand);
  187.       preemptReg(regs_scratch, 1);
  188.       generateKernelCall("em_tryview");
  189.     } else IFOPTION(view, 2) {
  190.       result.data.kind = DD_OIDToCodePtr;
  191.       result.data.value.id = q->b.atlit.id;
  192.       ensureGenerate(q->b.atlit.id);
  193.       result.abCon = buildConCon(SIGNATUREINDEX);
  194.       moveDataToRegister(&result, regs_arg3, ODPBrand);
  195.       preemptReg(regs_scratch, 1);
  196.       generateKernelCall("em_tryviewptr");
  197.     } else {
  198.       assert(FALSE);
  199.     }
  200.     vDiscard();
  201.     freeReg(regs_arg3, 1);
  202.     claimReg(regs_arg1, 2, VariableBrand);
  203.     result.data = buildRegisterDD(regs_arg1);
  204.     result.abCon = nextAddress(result.data);
  205.     setDDAbstractType(result.abCon, q->b.atlit.id);
  206.     vPush(result);
  207.       }
  208.       break;
  209.     case P_RESTRICT:
  210.       generateExpression(p->b.restrict.exp, anyContext);
  211.       v = vPeek(0);
  212.       q = newExecuteAsAT(p->b.restrict.type);
  213.       assert(q->tag == P_ATLIT);
  214.       moveVariableToRegisters(v, regs_arg1);
  215.       result.data.kind = DD_OIDToCodePtr;
  216.       result.data.value.id = q->b.atlit.id;
  217.       ensureGenerate(q->b.atlit.id);
  218.       result.abCon = buildConCon(SIGNATUREINDEX);
  219.       moveDataToRegister(&result, regs_arg3, ODPBrand);
  220.       preemptReg(regs_scratch, 1);
  221.       generateKernelCall("em_restrictptr");
  222.       vDiscard();
  223.       freeReg(regs_arg3, 1);
  224.       claimReg(regs_arg1, 2, VariableBrand);
  225.       result.data = buildRegisterDD(regs_arg1);
  226.       result.abCon = nextAddress(result.data);
  227.       setDDAbstractType(result.abCon, q->b.atlit.id);
  228.       vPush(result);
  229.       break;
  230.     default:
  231.       ErrorMessage(p, "Garbage in generateExpression");
  232.       assert(FALSE);
  233.       vPush(result);
  234.       break;
  235.   }
  236. }
  237.  
  238. Boolean allAreManifest(p)
  239. register NodePtr p;
  240. {
  241.   register NodePtr q;
  242.   Sequence_For(q, p->b.vectorlit.exp)
  243.     if (!isATrivialLiteral(q)) return(FALSE);
  244.     if (q->tag == P_STRINGLIT) return(FALSE);
  245.   Sequence_Next
  246.   return(TRUE);
  247. }
  248.  
  249. void generateVectorLiteral(p)
  250. NodePtr p;
  251. {
  252.   NodePtr vt, q, instct;
  253.   Symbol elementTypeSymbol;
  254.   int elementTypeSize;
  255.   Variable etsv, *ets = &etsv, ctv, *ct = &ctv, result, nev, *ne = &nev;
  256.   
  257.   assert(p->tag == P_VECTORLIT);
  258.   vt = p->b.vectorlit.vectorType;
  259.   assert(vt != NN);
  260.   vt = GETVALUE(vt);
  261.   assert(vt->tag == P_OBLIT);
  262.   assert(vt->b.oblit.f.writeSeparately);
  263.   assert(vt->b.oblit.f.isManifest);
  264.   assert(vt->b.oblit.id != 0);
  265.   ensureGenerate(vt->b.oblit.id);
  266.  
  267.   instct = findInstCode(vt);
  268.   assert(instct != NULL);
  269.   assert(instct->tag == P_OBLIT);
  270.  
  271.   ct->data.kind = DD_OIDToCodePtr;
  272.   ct->data.value.id = getCodeOID(instct);
  273.   ct->abCon = buildAbConFromObject(instct);
  274.  
  275.   elementTypeSymbol = getElementTypeSymbol(instct);
  276.   elementTypeSize = getSymbolSize(elementTypeSymbol);
  277.  
  278.   if (allAreManifest(p)) {
  279.     if (!doGenerateCode) 
  280.       TRACE1(generate, 1, "A manifest vectorliteral on line %d",
  281.     p->lineNumber);
  282.     result.data.kind = DD_Label;
  283.     result.data.value.label = nextLabelNumber++;
  284.     result.abCon = ct->abCon;
  285.     squirrelVectorLiteral(result.data.value.label, p, elementTypeSize,
  286.       getCodeOID(instct));
  287.     vPush(result);
  288.     return;
  289.   }
  290.   TS_StartInvocation();
  291.   IFOPTION(createonstack, 1) {
  292.     emitMove(ct->abCon, pusher, 'l');
  293.     emitMove(nilDD, pusher, 'l');
  294.   }
  295.  
  296.   Sequence_For(q, p->b.vectorlit.exp)
  297.     vPush(pusherContext.v);
  298.     generateExpression(q, pusherContext);
  299.     vGenerateAssign();
  300.     TS_Push();
  301.   Sequence_Next
  302.   TS_EndInvocation();
  303.  
  304.   ne->data = buildManifestDD(Sequence_Length(p->b.vectorlit.exp));
  305.   ne->abCon = buildConCon(INTEGERINDEX);
  306.   moveDataToRegister(ne, regs_arg3, DataBrand);
  307.  
  308.   ets->data = buildManifestDD(elementTypeSize);
  309.   ets->abCon = buildConCon(INTEGERINDEX);
  310.   moveDataToRegister(ets, regs_arg2, DataBrand);
  311.  
  312.   result.abCon = ct->abCon;
  313.   moveDataToRegister(ct, regs_arg1, ODPBrand);
  314.  
  315.   preemptReg(regs_scratch, 1);
  316. #ifdef MUTABLEVECTORLITERALS
  317.   if (OPTION(locals, 1) && p->b.vectorlit.f.doLocalCreate) {
  318.     generateKernelCall("em_localCreateVectorLiteral");
  319.   } else {
  320.     generateKernelCall("em_globalCreateVectorLiteral");
  321.   }
  322. #else
  323.   generateKernelCall("em_localCreateVectorLiteral");
  324. #endif
  325.   FREEV(ets);
  326.   FREEV(ct);
  327.   FREEV(ne);
  328.   claimReg(regs_arg1, 1, ODPBrand);
  329.   result.data = buildRegisterDD(regs_arg1);
  330.   IFOPTION(createonstack, 1) {
  331.     emitMove(popper, result.data, 'l');
  332.     emit(POPABCON);
  333.   }
  334.   vPush(result);
  335. }
  336.  
  337.  
  338. /*ARGSUSED*/
  339. void generateExp(p, c)
  340. NodePtr p;
  341. Context c;
  342. {
  343.   Variable resultV, *result = &resultV, *left, *right, answer, rightV, leftV;
  344.   Variable temp;
  345.   NodePtr q, r, eleft;
  346.   int truelabel, falselabel, endlabel;
  347.   result->data = nullDD;
  348.   result->abCon = nullDD;
  349.  
  350.   assert(p->tag == P_EXP);
  351.   switch (p->b.exp.op) {
  352.     case KOR:
  353.       findTemp(result, 4, DataBrand);
  354.       result->abCon = buildConCon(BOOLEANINDEX);
  355.       vPush(*result);
  356.       result = vPeek(0);
  357.       truelabel = nextLabelNumber++;
  358.       falselabel = nextLabelNumber++;
  359.       endlabel = nextLabelNumber++;
  360.       generateExpression(p->b.exp.left, pslContext);
  361.       generateBranch(TRUE, truelabel);
  362.       generateExpression(p->b.exp.right, pslContext);
  363.       generateBranch(TRUE, truelabel);
  364.       answer.data = buildManifestDD(0);
  365.       answer.abCon = buildConCon(BOOLEANINDEX);
  366.       ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
  367.       emit("\tj%s\tL_%d\n", JN(ALWAYS), endlabel);
  368.       emit("L_%d:\n", truelabel);
  369.       answer.data = buildManifestDD(1);
  370.       answer.abCon = buildConCon(BOOLEANINDEX);
  371.       ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
  372.       emit("L_%d:\n", endlabel);
  373.       break;
  374.     case KAND:
  375.       findTemp(result, 4, DataBrand);
  376.       vPush(*result);
  377.       result = vPeek(0);
  378.       result->abCon = buildConCon(BOOLEANINDEX);
  379.       truelabel = nextLabelNumber++;
  380.       falselabel = nextLabelNumber++;
  381.       endlabel = nextLabelNumber++;
  382.       generateExpression(p->b.exp.left, pslContext);
  383.       generateBranch(FALSE, falselabel);
  384.       generateExpression(p->b.exp.right, pslContext);
  385.       generateBranch(FALSE, falselabel);
  386.       answer.data = buildManifestDD(1);
  387.       answer.abCon = buildConCon(BOOLEANINDEX);
  388.       ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
  389.       emit("\tj%s\tL_%d\n", JN(ALWAYS), endlabel);
  390.       emit("L_%d:\n", falselabel);
  391.       answer.data = buildManifestDD(0);
  392.       answer.abCon = buildConCon(BOOLEANINDEX);
  393.       ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
  394.       emit("L_%d:\n", endlabel);
  395.       break;
  396.     case OIDENTITY:
  397.     case ONOTIDENTITY:
  398.       result->abCon = buildConCon(BOOLEANINDEX);
  399.       generateExpression(p->b.exp.left, anyContext);
  400.       left = vPeek(0);
  401.       vForceToTemp(left, TS_All);
  402.       generateExpression(p->b.exp.right, anyContext);
  403.       right = vPeek(0);
  404.       vForceToTemp(right, TS_All);
  405.       currentInstruction = nextLabelNumber++;
  406.       result->data = 
  407.     generateCompare(left, right, 'l', p->b.exp.op == OIDENTITY ? EQL : NEQ);
  408.       vDiscard();
  409.       vDiscard();
  410.       vPush(*result);
  411.       break;
  412.     case OCONFORMSTO:
  413.       /* Try to execute the left operand as an AT. */
  414.       r = tryToExecuteAsAT(p->b.exp.left);
  415.       if (r == NULL) {
  416.     eleft = p->b.exp.left;
  417.     if (! conforms(evaluateForAT(eleft, TRUE),
  418.           refToBuiltin(B_INSTAT, SIGNATUREINDEX))) {
  419.       eleft = Construct(P_INVOC, 3, 
  420.         eleft, 
  421.         buildOpName("getsignature", -1),
  422.         NN);
  423.     }
  424.     generateExpression(eleft, anyContext);
  425.     left = vPeek(0);
  426.     moveDataToRegister(left, regs_arg1, DataBrand);
  427.     emitMove(buildAddressDD(regs_arg1, /* Code_ownOID */ 4), buildRegisterDDNC(regs_arg1), 'l');
  428.       } else {
  429.     assert(r->tag == P_ATLIT);
  430.     assert(r->b.atlit.id != 0);
  431.     left = &leftV;
  432.     left->abCon = buildConCon(INTEGERINDEX);
  433.     left->data = buildManifestDD((int)r->b.atlit.id);
  434.     ensureGenerate(r->b.atlit.id);
  435.     moveDataToRegister(left, regs_arg1, DataBrand);
  436.       }
  437.       q = newExecuteAsAT(p->b.exp.right);
  438.       assert(q != NULL);
  439.       assert(q->tag == P_ATLIT);
  440.       assert(q->b.atlit.id != 0);
  441.       right = &rightV;
  442.       right->abCon = buildConCon(INTEGERINDEX);
  443.       right->data = buildManifestDD((int)q->b.atlit.id);
  444.       ensureGenerate(q->b.atlit.id);
  445.       moveDataToRegister(right, regs_arg2, DataBrand);
  446.       preemptReg(regs_scratch, 1);
  447.       preemptReg(regs_arg3, 1);
  448.       generateKernelCall("em_conform");
  449.       FREEV(left);
  450.       FREEV(right);
  451.       claimReg(regs_arg1, 1, DataBrand);
  452.       result->abCon = buildConCon(BOOLEANINDEX);
  453.       result->data = buildRegisterDD(regs_arg1);
  454.       if (r == NULL) {
  455.     vDiscard();
  456.       }
  457.       vPush(*result);
  458.       break;
  459.     default:
  460.       assert(FALSE);
  461.       break;
  462.   }
  463. }
  464.  
  465. /*ARGSUSED*/
  466. void generateUnaryExp(p, c)
  467. NodePtr p;
  468. Context c;
  469. {
  470.   Variable result;
  471.  
  472.   assert(p->tag == P_UNARYEXP);
  473.   switch (p->b.unaryexp.op) {
  474.     case KAWAITING:
  475.       generateExpression(p->b.unaryexp.exp, anyContext);
  476.       moveDataToRegister(vPeek(0), regs_arg1, ODPBrand);
  477.       preemptReg(regs_scratch, 1);
  478.       preemptReg(regs_arg2, 2);
  479.       generateKernelCall("em_condAwaiting");
  480.       vDiscard();
  481.       claimReg(regs_arg1, 1, DataBrand);
  482.       result.data = buildRegisterDD(regs_arg1);
  483.       result.abCon = buildConCon(BOOLEANINDEX);
  484.       break;
  485.     case KISFIXED:
  486.       generateExpression(p->b.unaryexp.exp, anyContext);
  487.       moveVariableToRegisters(vPeek(0), regs_arg1);
  488.       preemptReg(regs_scratch, 1);
  489.       preemptReg(regs_arg3, 1);
  490.       generateKernelCall("em_isFixed");
  491.       vDiscard();
  492.       claimReg(regs_arg1, 1, DataBrand);
  493.       result.data = buildRegisterDD(regs_arg1);
  494.       result.abCon = buildConCon(BOOLEANINDEX);
  495.       break;
  496.     case KLOCATE:
  497.       generateExpression(p->b.unaryexp.exp, anyContext);
  498.       moveVariableToRegisters(vPeek(0), regs_arg1);
  499.       preemptReg(regs_scratch, 1);
  500.       preemptReg(regs_arg3, 1);
  501.       INC(cEM_locates);
  502.       generateKernelCall("em_locate");
  503.       vDiscard();
  504.       claimReg(regs_arg1, 1, ODPBrand);
  505.       result.data = buildRegisterDD(regs_arg1);
  506.       result.abCon = buildConCon(NODEINDEX);
  507.       break;
  508.     default:
  509.       assert(FALSE);
  510.       break;
  511.   }
  512.   vPush(result);
  513. }
  514.